package com.yunxi.service.dubboService.impl.otd;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yunxi.core.util.StringUtil;
import com.yunxi.core.web.ApiResult;
import com.yunxi.core.web.ResponseUtil;
import com.yunxi.model.otd.OtdOrderCir;
import com.yunxi.model.otd.OtdOrderCirMonth;
import com.yunxi.model.otd.OtdOrderMonth;
import com.yunxi.model.otd.OtdOrderMonthVersion;
import com.yunxi.otd.pojo.OtdOrderMonthEditVO;
import com.yunxi.otd.pojo.OtdOrderMonthImportVO;
import com.yunxi.otd.pojo.OtdOrderMonthQueryVO;
import com.yunxi.otd.pojo.OtdOrderMonthReleaseVO;
import com.yunxi.otd.service.OtdOrderMonthDubboService;
import com.yunxi.service.localService.CodeCreateService;
import com.yunxi.service.localService.VehicleProductViewService;
import com.yunxi.service.localService.otd.OtdOrderCirMonthService;
import com.yunxi.service.localService.otd.OtdOrderMonthService;
import com.yunxi.service.localService.otd.OtdOrderMonthVersionService;
import com.yunxi.service.localService.otd.OtdOrderSoService;
import com.yunxi.service.localService.otd.OtdProduceCalendarService;
import com.yunxi.service.localService.otd.VehicleConfigConstraintService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 月排产需求订单 服务实现类
 * </p>
 *
 * @author XUQI
 * @since 2019-07-15
 */
public class OtdOrderMonthDubboServiceImpl implements OtdOrderMonthDubboService {

    @Autowired
    @Qualifier(value = "otdOrderMonthServiceImpl")
    OtdOrderMonthService otdOrderMonthService;

    @Autowired
    @Qualifier(value = "otdOrderMonthVersionServiceImpl")
    OtdOrderMonthVersionService monthVersionService;

    @Autowired
    @Qualifier(value = "vehicleProductViewServiceImpl")
    VehicleProductViewService productService;

    @Autowired
    @Qualifier("codeCreateServiceImpl")
    CodeCreateService code;

    @Autowired
    @Qualifier(value = "otdOrderSoServiceImpl")
    OtdOrderSoService soService;

    @Autowired
    @Qualifier(value = "otdOrderCirMonthServiceImpl")
    OtdOrderCirMonthService cirMonthService;

    @Autowired
    @Qualifier("otdProduceCalendarServiceImpl")
    OtdProduceCalendarService produceCalendarService;

    @Autowired
    @Qualifier("vehicleConfigConstraintServiceImpl")
    VehicleConfigConstraintService configConstraintService;

    /**
     * 分页查询
     *
     * @param queryVO 查询条件
     * @return 分页对象
     */
    @Override
    public ApiResult page(OtdOrderMonthQueryVO queryVO) {
        return ResponseUtil.ok(otdOrderMonthService.findMonthPlan(queryVO));
    }

    /**
     * 导入月计划
     *
     * @param importVO 导入VO
     * @return ApiResult
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult importData(OtdOrderMonthImportVO importVO) {

        // 年份
        String year = importVO.getYear();
        //制作版本
        OtdOrderMonthVersion monthVersion = monthVersionService.getById(importVO.getVersionId());

        //是否新增版本
        boolean isAdd = monthVersion == null;
        if (isAdd) {
            if (StringUtils.isEmpty(importVO.getMadeVersion())) {
                return ResponseUtil.fail(-1, "新增版本名称不能为空");
            }
            LambdaQueryWrapper<OtdOrderMonthVersion> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OtdOrderMonthVersion::getMadeVersion, importVO.getMadeVersion());
            int count = monthVersionService.count(wrapper);
            if (count > 0) {
                return ResponseUtil.fail(-1, "版本名称已存在");
            }
            // 新增版本
            monthVersion = new OtdOrderMonthVersion();
            monthVersion.setMadeVersion(importVO.getMadeVersion());
            monthVersion.setIsDefault(0);
            monthVersion.setState("1");
            monthVersionService.save(monthVersion);
        } else {
            // 覆盖导入删除原版本月计划
            LambdaQueryWrapper<OtdOrderMonth> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OtdOrderMonth::getVersionId, monthVersion.getId())
                .eq(OtdOrderMonth::getYear, year);
            otdOrderMonthService.remove(wrapper);
        }
        //制作版本ID
        String versionId = monthVersion.getId();

        // 导入数据集合
        List<Map<String, Object>> dataList = importVO.getDataList();
        if (CollectionUtils.isEmpty(dataList)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseUtil.fail(-1, "导入数据为空");
        }

        // 验证导入数据是否存在重复行
        try {
            checkImportDataRepeat(dataList);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseUtil.fail(-1, e.getMessage());
        }

        for (Map<String, Object> map : dataList) {
            // 产品CODE
            String productCode = productService
                .findProductCodeBySub((String) map.get("配置"), (String) map.get("内饰色"),
                    (String) map.get("外饰色"));
            if (StringUtils.isEmpty(productCode)) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ResponseUtil.fail(-1, "产品信息填写错误");
            }
            //选装包CODES
            String customPackCode = (String) map.get("选装包");
            if (customPackCode != null) {
                customPackCode = StringUtil.customPackCodeSort(customPackCode.replace("/", ","));
            }

            // 添加月需求订单
            for (Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (checkMonth(key)) {
                    // 月份
                    String month = key.length() == 1 ? "0" + key : key;
                    OtdOrderMonth order = new OtdOrderMonth();
                    order.setVersionId(versionId);
                    order.setYear(year);
                    order.setMonth(month);
                    order.setProductCode(productCode);
                    order.setCustomPackCode(StringUtils.isEmpty(customPackCode) ? null : customPackCode);
                    order.setCarName(soService.generateCarName(productCode, customPackCode));
                    order.setWorks("AP21");
                    order.setOrderNum(Integer.valueOf((String) value));
                    otdOrderMonthService.saveOrUpdate(order);
                }
            }
        }
        return ResponseUtil.ok();
    }

    /**
     * 验证导入数据是否存在重复行
     *
     * @param dataList 导入数据
     */
    private void checkImportDataRepeat(List<Map<String, Object>> dataList) throws Exception {
        // List<产品CODE+选装包CODE>
        List<String> checkRepeatList = new ArrayList<>();
        for (Map<String, Object> map : dataList) {
            String vehicleCode = (String) map.get("配置");
            String inCode = (String) map.get("内饰色");
            String outCode = (String) map.get("外饰色");
            String customPackCode = StringUtil.customPackCodeSort((String) map.get("选装包"));
            if (StringUtils.isEmpty(vehicleCode)) {
                throw new RuntimeException("第" + (checkRepeatList.size() + 1) + "行配置不能为空");
            }
            if (StringUtils.isEmpty(inCode)) {
                throw new RuntimeException("第" + (checkRepeatList.size() + 1) + "行内饰色不能为空");
            }
            if (StringUtils.isEmpty(outCode)) {
                throw new RuntimeException("第" + (checkRepeatList.size() + 1) + "行外饰色不能为空");
            }

            // 选装包校验
            if (!StringUtils.isEmpty(customPackCode)) {
                // 是否正确、是否存在互斥
                List<String> packages = Arrays.asList(customPackCode.split("/"));
                boolean check = configConstraintService.checkExcludeCustomPackCode(packages, vehicleCode);
                if(!check){
                    throw new RuntimeException("选装包存在互斥：" + customPackCode);
                }
                customPackCode = StringUtil.customPackCodeSort(customPackCode.replace("/", ","));
            }

            // 产品CODE
            String code = vehicleCode + inCode + outCode;
            // 验证导入数据是否存在重复行
            if (!checkRepeatList.contains(code + customPackCode)) {
                checkRepeatList.add(code + customPackCode);
            } else {
                throw new RuntimeException("第" + (checkRepeatList.size() + 1) + "行重复");
            }
        }
    }

    /**
     * 月计划数量编辑
     *
     * @param editVO 编辑VO
     * @return ApiResult
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult editNum(OtdOrderMonthEditVO editVO) {
        if (editVO.getMonth().length() == 1) {
            editVO.setMonth("0" + editVO.getMonth());
        }
        //查询原数量判断新增还是减少数量
        LambdaQueryWrapper<OtdOrderMonth> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OtdOrderMonth::getVersionId, editVO.getVersionId())
            .eq(OtdOrderMonth::getProductCode, editVO.getProductCode())
            .eq(OtdOrderMonth::getYear, editVO.getYear())
            .eq(OtdOrderMonth::getMonth, editVO.getMonth());

        if (StringUtils.isEmpty(editVO.getCustomPackCode())) {
            queryWrapper.isNull(OtdOrderMonth::getCustomPackCode);
        } else {
            queryWrapper.eq(OtdOrderMonth::getCustomPackCode, editVO.getCustomPackCode());
        }
        OtdOrderMonth orderMonth = otdOrderMonthService.getOne(queryWrapper);
        if (orderMonth == null) {
            orderMonth = new OtdOrderMonth();
            orderMonth.setProductCode(editVO.getProductCode());
            orderMonth.setCarName(soService.generateCarName(editVO.getProductCode(), editVO.getCustomPackCode()));
            orderMonth.setCustomPackCode(editVO.getCustomPackCode());
            orderMonth.setVersionId(editVO.getVersionId());
            orderMonth.setYear(editVO.getYear());
            orderMonth.setMonth(editVO.getMonth());
            orderMonth.setWorks("AP21");
        }
        orderMonth.setOrderNum(editVO.getNum());
        otdOrderMonthService.saveOrUpdate(orderMonth);
        return ResponseUtil.ok();
    }

    /**
     * 释放月计划
     *
     * @param releaseVO releaseVO
     * @return ApiResult
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult release(OtdOrderMonthReleaseVO releaseVO) {
        String versionId = releaseVO.getMonthVersionId();
        List<String> yearMonths = releaseVO.getYearMonths();
        if (StringUtils.isEmpty(versionId)) {
            return ResponseUtil.fail(-1, "未选择版本");
        }
        if (CollectionUtils.isEmpty(yearMonths)) {
            return ResponseUtil.fail(-1, "未选择月份");
        }
        //// 查询需要释放的月计划
        Map<String, Object> map = new HashMap<>();
        map.put("yearMonths",yearMonths);
        map.put("versionId",versionId);
        List<OtdOrderMonth> orderMonths = otdOrderMonthService.listBy(map);
        if(CollectionUtils.isEmpty(orderMonths)){
            return ResponseUtil.fail(-1, "未找到可释放月计划");
        }

//        // 查询是否有接口待回馈数据，有则不允许覆盖释放
//        int count = cirMonthService
//            .findWaitCirOrderCountByYearMonth(yearMonths);
//        if (count > 0) {
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseUtil.fail(-1,  "所选释放月中存在待反馈的CIR订单，请稍后重试");
//        }
        // 删除原释放CIR数量
        cirMonthService.deleteCirOrderByYearMonth(yearMonths);

        List<OtdOrderCirMonth> cirList = new ArrayList<>();
        //// 释放月计划
        for (OtdOrderMonth orderMonth : orderMonths) {
            if (orderMonth.getOrderNum() == 0) {
                // 数量0，跳过
                continue;
            }

            // 根据年月查询生产工作日历
            List<Date> days = produceCalendarService
                .findWorkDayByYearMonth(orderMonth.getYear() + orderMonth.getMonth(),"1");
            if (CollectionUtils.isEmpty(days)) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ResponseUtil.fail(-1, orderMonth.getYear() + "年" + orderMonth.getMonth() + "月没有维护工作日");
            }
            //每天平均数4
            int avgNum = orderMonth.getOrderNum() / days.size();
            // 余数
            int modNum = orderMonth.getOrderNum() % days.size();

            /////平均分配数量
            for (int i = 1; i <= days.size(); i++) {
                // 需求数量
                int orderNum = avgNum;

                if (orderNum == 0) {
                    // 当总数小于天数时
                    if (modNum == 0) {
                        break;
                    }
                    orderNum = 1;
                    modNum--;
                } else {
                    // 判断余数
                    if (modNum > 0) {
                        orderNum++;
                        modNum--;
                    }
                }

                //// 添加CIR订单
                OtdOrderCirMonth orderCir = new OtdOrderCirMonth();
                orderCir.setProductCode(orderMonth.getProductCode());
                orderCir.setCustomPackCode(orderMonth.getCustomPackCode());
                orderCir
                    .setCarName(soService.generateCarName(orderMonth.getProductCode(), orderMonth.getCustomPackCode()));
                orderCir.setDemandDate(days.get(i - 1));
                orderCir.setOrderNum(orderNum);
                orderCir.setWorks("AP21");
                cirList.add(orderCir);
            }
        }
        if(!CollectionUtils.isEmpty(cirList)){
            cirMonthService.saveBatch(cirList);
        }
        return ResponseUtil.ok();
    }

    /**
     * 校验是否为月份（1-12）
     *
     * @param month 月份
     * @return 是 true 否 false
     */
    private boolean checkMonth(String month) {
        Pattern pattern = Pattern.compile("^0?[1-9]|1[0-2]$");
        return pattern.matcher(month).matches();
    }


}
